package com.zl.autocode.common.utils.generator;

import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.sql.DataSource;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.zl.autocode.common.constant.AutocodeConfigC;
import com.zl.autocode.common.utils.generator.model.ConvertColumn;
import com.zl.autocode.common.utils.generator.model.ConvertConfig;
import com.zl.autocode.common.utils.generator.model.ConvertSequence;
import com.zl.autocode.common.utils.generator.model.ConvertTable;
import com.zl.autocode.common.utils.generator.util.TableTitleUtil;
import com.zl.autocode.dao.generator.IGeneratorDao;
import com.zl.common.enums.resp.GlobalRespEnum;
import com.zl.common.exception.BizException;

import cn.hutool.core.util.StrUtil;
import cn.hutool.db.ds.simple.SimpleDataSource;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component("database"+AutocodeConfigC.GENERATOR_READER_KEY)
public class ReaderDatabase implements IReaderData<ConvertConfig> {
    
    private static String DEFAULT_TYPE = "默认分类";
    private static String DEFAULT_ENCODE = "UTF-8";
    
    @Autowired
    private  Map<String,IGeneratorDao> generatorDao;
    @Autowired
    protected DataSource dynamicDataSource;
    
    @Override
    public void parseData(ConvertConfig config) throws Exception {
        // TODO Auto-generated method stub
        log.info("数据库加载方式");
        parseTable(config, true);
    }
    
    @Override
    public Map<String,Object> getData(ConvertConfig config) throws Exception {
        // TODO Auto-generated method stub
        Map<String,Object>  result = new HashMap<>();
        
        parseTable(config, false);
        result.put("tables", config.getTbls());

        return result;
    }
    
    public void parseTable(ConvertConfig config,boolean tableFlag) throws Exception {
        // TODO Auto-generated method stub
        try{
            IGeneratorDao gdao =  null;
            String cdskey = AutocodeConfigC.DDS_KEY + config.getProjectId().toString();
            if(StringUtils.isNotBlank(config.getJdbcUrl())){
                DynamicRoutingDataSource dynamicRoutingDataSource = (DynamicRoutingDataSource)dynamicDataSource;
                if(dynamicRoutingDataSource.getDataSources().get(cdskey)==null){
                    SimpleDataSource dynamicDataSourceVO = new SimpleDataSource(config.getJdbcUrl(), config.getJdbcLoginname(), config.getJdbcPassword());
                    dynamicRoutingDataSource.addDataSource(cdskey, dynamicDataSourceVO);
                }
                DynamicDataSourceContextHolder.push(cdskey);
                
                gdao = getDatebaseDaoHandler(config.getDatabaseType());
            }else{
                gdao = getDatebaseDaoHandler(null);
            }
            
            List<String> loadTables = config.getLoadTables();
            if(loadTables != null && loadTables.size()>0){
                List<ConvertTable>  tableLists = new ArrayList<>();
                List<String> hasTables =  new ArrayList<>();
                String queryType= StringUtils.isNotBlank(config.getQueryType())?config.getQueryType():"0";
                for(int ti=0,tblln=loadTables.size();ti<tblln;ti++){
                    String tableCodex=loadTables.get(ti);
                    tableCodex = "1".equals(queryType)? "%"+tableCodex+"%" :tableCodex;
                    List<ConvertTable> tables  = gdao.queryTables(tableCodex,queryType,ti==tblln-1);
                    for(int ti2=0,tblln2=tables.size();ti2<tblln2;ti2++){
                        ConvertTable tbl=tables.get(ti2);
                        tbl.setTableTag(DEFAULT_TYPE);
                        tbl.setTableName(tbl.getTableCode());//原始编号
                        tbl.setTableCode(tbl.getTableCode().toLowerCase());
                        if(hasTables.contains(tbl.getTableCode())){
                            continue;
                        }
                        hasTables.add(tbl.getTableCode());
                        
                        if(StrUtil.isBlank(tbl.getTableTitle())){
                            tbl.setTableTitle(TableTitleUtil.praseTitleByPattern(tbl.getTableComment(),tbl.getTableCode()));
                        }else{
                            tbl.setTableTitle(TableTitleUtil.praseTitleByPattern(tbl.getTableTitle(),tbl.getTableCode()));
                        }
                        if(tableFlag){
                            List<ConvertColumn> columns = gdao.queryTableColumns(tbl.getTableCode(),ti2==tblln2-1);
                            for(ConvertColumn col : columns){
                                col.setColumnName(col.getColumnCode());
                                col.setColumnCode(col.getColumnCode().toLowerCase());
                                if(StrUtil.isBlank(col.getColumnTitle())){
                                    col.setColumnTitle(TableTitleUtil.praseTitleByPattern(col.getColumnComment(),col.getColumnCode()));
                                }else{
                                    col.setColumnTitle(TableTitleUtil.praseTitleByPattern(col.getColumnTitle(),col.getColumnCode()));
                                }
                            }
                            tbl.setAllcols(columns); 
                        }
                        
                        tableLists.add(tbl);
                    }
                }
                
                config.setTbls(tableLists);
            }
            
            List<String> loadSeqs = config.getLoadSeqs();
            if(loadSeqs!=null && loadSeqs.size()>0){
                List<ConvertSequence>  sequenceLists =  new ArrayList<>();
                
                config.setSeqs(sequenceLists);
            }
        }finally {
            DynamicDataSourceContextHolder.clear();
        }
    }
    
    private IGeneratorDao getDatebaseDaoHandler(String databaseType) throws SQLException{
       if(generatorDao != null){
           if(StringUtils.isNotBlank(databaseType)){
               for(Entry<String, IGeneratorDao> entryx :generatorDao.entrySet()){
                   if(entryx.getKey().equalsIgnoreCase(databaseType + AutocodeConfigC.GENERATOR_DAO_KEY)){
                       return entryx.getValue();
                   }
               }
           }else{
               DatabaseMetaData metaData = dynamicDataSource.getConnection().getMetaData();
               databaseType = metaData.getURL().toLowerCase();
               for(Entry<String, IGeneratorDao> entryx :generatorDao.entrySet()){
                   String key = entryx.getKey().substring(0,entryx.getKey().lastIndexOf(AutocodeConfigC.GENERATOR_DAO_KEY));
                   if(databaseType.indexOf(":" + key.toLowerCase() + ":") != -1){
                       return entryx.getValue();
                   }
               }
           }
       }
       log.info("当前数据库未实现读取表结构方法");
       throw new BizException(GlobalRespEnum.METHOD_NOT_IMPLEMENTED);
    }
}
